package com.lfy.order.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.lfy.api.product.ProductFeignClient;
import com.lfy.order.bean.Order;

import com.lfy.order.properties.OrderProperties;
import com.lfy.product.bean.Product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
//@RefreshScope
@RestController
@Slf4j
public class OrederRestController {
    @Autowired
    RestTemplate restTemplate;

    @Autowired
    DiscoveryClient discoveryClient;
    @Autowired
    LoadBalancerClient loadBalancerClient;
//自动从配置文件拿东西，没有从配置文件拿
    @Value("${order.timeout}")
    String timeout;
    @Value("${order.auto-confirm}")
    String autoConfirm;
    @Value("${order.haha}")
    String haha;


    @Autowired
    OrderProperties orderProperties;

    @Autowired
    ProductFeignClient productFeignClient;

    @GetMapping("/config")

    public String orderConfigInfo(){
        String result="订单超时：" +timeout +" , 订单自动确认：" + autoConfirm;
        try(Entry entry = SphU.entry("haha");) {
            String str = "订单超时：" +timeout +" , 订单自动确认：" + autoConfirm + " , 哈哈：" + haha;
            String plus = orderProperties.getTimeout() + "~~~" + orderProperties.getAutoConfirm();
            result = str + "\n" + plus;
        } catch (BlockException e) {
            //sentinel如果不允许访问这个资源就会来到异常
            throw new RuntimeException(e);
        }
        return result;
    }

    @GetMapping("/createorder")
    public Order createOrder(@RequestParam("userId") Long userId,
                             @RequestParam("productId") Long productId) {
//        1.创建订单
        Order order = new Order();
        order.setId(1L);
        order.setUserId(userId);

        order.setNickname("张三");
        order.setAddress("上海");

        // 参数验证
        if (userId == null || productId == null) {
            throw new IllegalArgumentException("用户ID和商品ID不能为空");
        }

//        远程调用
        Product product = getProductFromRemoteV6(productId);

        // 空值检查
        if (product == null) {
            throw new RuntimeException("未找到指定的商品信息");
        }

//        动态计算
        BigDecimal price = product.getPrice();
        BigDecimal decimal = price.multiply(new BigDecimal(product.getNum()));
        order.setTotalAmount(decimal);
        order.setProductList(Arrays.asList(product));


        return order;
    }
    /**
     * v1:直接调用url
     */

    private Product getProductFromRemoteV1(Long productId){
        RestTemplate localRestTemplate = new RestTemplate();
        String url = "http://localhost:9000/product/get/"+productId;
        Product product = restTemplate.getForObject(url , Product.class);
        return product;

    }
    /**
     * v2:通过注册中心调用
     */
    private Product getProductFromRemoteV2(Long productId){
        try {
            List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
            if (instances == null || instances.isEmpty()) {
                throw new RuntimeException("未找到可用的product-service服务实例");
            }
            ServiceInstance instance = instances.get(0);
            String host = instance.getHost();
            int port = instance.getPort();
            String url = "http://"+host+":"+port+"/product/get/"+productId;
            log.info("v2远程调用url:{}",url);
            Product product = restTemplate.getForObject(url, Product.class);
            return product;
        } catch (Exception e) {
            log.error("调用product-service服务失败, productId:{}", productId, e);
            throw new RuntimeException("调用商品服务失败", e);
        }
    }

    /**
     * v3:通过注册中心调用,使用负载均衡
     */
    private Product getProductFromRemoteV3(Long productId){
        try {
            ServiceInstance choose = loadBalancerClient.choose("product-service");
            if (choose == null) {
                throw new RuntimeException("无法找到可用的product-service服务实例");
            }
            String url = "http://"+choose.getHost()+":"+choose.getPort()+"/product/get/"+productId;
            log.info("v3远程调用url:{}",url);
            Product product = restTemplate.getForObject(url, Product.class);
            return product;
        } catch (Exception e) {
            log.error("调用product-service服务失败, productId:{}", productId, e);
            throw new RuntimeException("调用商品服务失败", e);
        }
    }

    /**
     * v4:通过注册中心调用,使用负载均衡,使用@LoadBalanced
     */
    private Product getProductFromRemoteV4(Long productId){
        try {
            String url = "http://product-service/product/get/"+productId;
            log.info("v4远程调用url:{}",url);
            Product product = restTemplate.getForObject(url, Product.class);
            return product;
        } catch (Exception e) {
            log.error("调用product-service服务失败, productId:{}", productId, e);
            throw new RuntimeException("调用商品服务失败", e);
        }
    }

    /**
     * v5:通过feign客户端调用
     */

    private Product getProductFromRemoteV5(Long productId){
        try {
            Product product = productFeignClient.getProduct(productId);
            return product;

        } catch (Exception e) {
            log.error("调用product-service服务失败, productId:{}", productId, e);
            throw new RuntimeException("调用商品服务失败", e);
        }
    }
    /*
    * 通过sentinel注解监控
    * */
    @SentinelResource("product-rpc")
    public Product getProductFromRemoteV6(Long productId){
        Product product = productFeignClient.getProduct(productId);

        return product;
    }

}
